

<!DOCTYPE html>
<html lang="en" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/avatar.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Hughie">
  <meta name="keywords" content="">
  
    <meta name="description" content="一、异常介绍什么是异常？异常是指程序在运行过程中发生的，由于外部问题导致的程序运行异常事件，异常的发生往往会中断程序的运行。在 Java 这种面向对象的编程语言中，万物都是对象，异常本身也是一个对象，程序发生异常就会产生一个异常对象。 异常的分类讲到异常的分类，就不能不说一下Java异常的继承结构。如下图所示：  从图中可以看到，异常主要有以下类构成：  Throwable Error Excep">
<meta property="og:type" content="article">
<meta property="og:title" content="Java异常">
<meta property="og:url" content="https://hughie-hy.gitee.io/2022/02/27/Java%E5%BC%82%E5%B8%B8/index.html">
<meta property="og:site_name" content="Hughie&#39;s blog">
<meta property="og:description" content="一、异常介绍什么是异常？异常是指程序在运行过程中发生的，由于外部问题导致的程序运行异常事件，异常的发生往往会中断程序的运行。在 Java 这种面向对象的编程语言中，万物都是对象，异常本身也是一个对象，程序发生异常就会产生一个异常对象。 异常的分类讲到异常的分类，就不能不说一下Java异常的继承结构。如下图所示：  从图中可以看到，异常主要有以下类构成：  Throwable Error Excep">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://hughie-hy.gitee.io/img/java.png">
<meta property="article:published_time" content="2022-02-27T11:51:56.000Z">
<meta property="article:modified_time" content="2022-02-27T18:04:46.773Z">
<meta property="article:author" content="Hughie">
<meta property="article:tag" content="Java基础">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://hughie-hy.gitee.io/img/java.png">
  
  
  <title>Java异常 - Hughie&#39;s blog</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hint.css@2/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"hughie-hy.gitee.io","root":"/","version":"1.8.14","typing":{"enable":true,"typeSpeed":120,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.1"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Hughie</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                Home
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                Archives
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                Categories
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                Tags
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                About
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="Java异常">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2022-02-27 19:51" pubdate>
        February 27, 2022 pm
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      20k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      163 分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Java异常</h1>
            
            <div class="markdown-body">
              <h2 id="一、异常介绍"><a href="#一、异常介绍" class="headerlink" title="一、异常介绍"></a>一、异常介绍</h2><h3 id="什么是异常？"><a href="#什么是异常？" class="headerlink" title="什么是异常？"></a><strong>什么是异常？</strong></h3><p>异常是指程序在运行过程中发生的，由于外部问题导致的程序运行异常事件，异常的发生往往会中断程序的运行。在 Java 这种面向对象的编程语言中，万物都是对象，异常本身也是一个对象，程序发生异常就会产生一个异常对象。</p>
<h3 id="异常的分类"><a href="#异常的分类" class="headerlink" title="异常的分类"></a><strong>异常的分类</strong></h3><p>讲到异常的分类，就不能不说一下Java异常的继承结构。如下图所示：</p>
<p><img src="https://blog-chy.oss-cn-shenzhen.aliyuncs.com/static/Exception_Classes.png" srcset="/img/loading.gif" lazyload alt="Exception_Classes"></p>
<p>从图中可以看到，异常主要有以下类构成：</p>
<ul>
<li>Throwable</li>
<li>Error</li>
<li>Exception</li>
</ul>
<p>接下来我们就分别介绍一下这几个基类的作用。</p>
<h3 id="Throwable"><a href="#Throwable" class="headerlink" title="Throwable"></a><strong>Throwable</strong></h3><p>Throwable 类是 Java 语言中所有错误或异常的顶层父类，其他异常类都继承于该类。Throwable类有两个重要的子类：<strong>Exception（异常）</strong>和 <strong>「Error（错误）」</strong>，二者都是 Java 异常处理的重要子类，各自都包含大量子类。</p>
<p>只有当对象是此类或其子类的实例时，才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地，只有此类或其子类才可以是 catch 子句中的参数类型。</p>
<p>Throwable 对象中包含了其线程创建时线程执行堆栈的快照，它还包含了给出有关错误更多信息的消息字符串。</p>
<p>最后，它还可以包含 cause（原因）：另一个导致此 throwable 抛出的 throwable。此 cause 设施在 1.4 版本中首次出现。它也称为异常链设施，因为 cause 自身也会有 cause，依此类推，就形成了异常链，每个异常都是由另一个异常引起的。</p>
<h3 id="Error"><a href="#Error" class="headerlink" title="Error"></a><strong>Error</strong></h3><p>Error 是 Throwable 的子类，通常情况下应用程序<strong>「不应该试图捕获的严重问题」</strong>。</p>
<p>Error 是程序无法处理的错误，表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关，而表示代码运行时 JVM（Java 虚拟机）出现的问题。</p>
<p>例如：Java虚拟机运行错误（Virtual MachineError），当 JVM 不再有继续执行操作所需的内存资源时，将出现 OutOfMemoryError。这些异常发生时，Java虚拟机（JVM）一般会选择线程终止。</p>
<p>这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时，如Java虚拟机运行错误（Virtual MachineError）、类定义错误（NoClassDefFoundError）等。这些错误是不可查的，因为它们在应用程序的控制和处理能力之 外，而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说，即使确实发生了错误，本质上也不应该试图去处理它所引起的异常状况。在 Java中，错误通过Error的子类描述。</p>
<h3 id="Exception"><a href="#Exception" class="headerlink" title="Exception"></a><strong>Exception</strong></h3><p>Exception以及它的子类，代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用，是异常处理的核心。</p>
<p>Exception 异常主要分为两类：</p>
<p><strong>「1、非检查性异常（unchecked exception）」</strong></p>
<p>Error 和 RuntimeException 以及他们的子类。Java语言在编译时，不会提示和发现这样的异常，不要求在程序中处理这些异常。所以我们可以在程序中编写代码来处理（使用try…catch…finally）这样的异常，也可以不做任何处理。对于这些错误或异常，我们应该修正代码，而不是去通过异常处理器处理。这样的异常发生的原因多半是由于我们的代码逻辑出现了问题。</p>
<p>例如：</p>
<ul>
<li>当程序中用数字除以0时，就会抛出ArithmeticException异常；</li>
<li>在类型转换时，错误的强制类型转换会抛出ClassCastException类型转换异常；</li>
<li>当使用集合进行数组索引越界时就会抛出ArrayIndexOutOfBoundsException异常；</li>
<li>当程序中使用了空对象进行操作时就会抛出注明的空指针NullPointerException异常等。</li>
</ul>
<p><strong>「2、检查性异常（checked exception）」</strong></p>
<p>除了Error 和 RuntimeException的其它异常。Java语言强制要求程序员为这样的异常做预备处理工作（使用try…catch…finally或者throws）。在方法中要么用try-catch语句捕获它并处理，要么用throws子句声明抛出它，否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下，而程序员无法干预用户如何使用他编写的程序，于是程序员就应该为这样的异常时刻准备着。如SQLException，IOException，ClassNotFoundException 等。</p>
<p>检查性异常就是指，编译器在编译期间要求必须得到处理的那些异常，你必须在编译期处理了。</p>
<h2 id="二、初识异常"><a href="#二、初识异常" class="headerlink" title="二、初识异常"></a>二、初识异常</h2><h3 id="常见异常的运行Demo"><a href="#常见异常的运行Demo" class="headerlink" title="常见异常的运行Demo"></a>常见异常的运行Demo</h3><figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.broky.exception.commonException;<br><br><span class="hljs-keyword">import</span> java.util.Scanner;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CommonEx</span> &#123;<br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">ArithmeticExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">a</span> <span class="hljs-operator">=</span> <span class="hljs-number">10</span>;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">b</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">c</span> <span class="hljs-operator">=</span> a / b;<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.ArithmeticException: / by zero</span><br><span class="hljs-comment">        at com.broky.exception.ArithmeticEx.main(ArithmeticEx.java:7)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">ClassCastExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">Object</span> <span class="hljs-variable">obj</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Double</span>(<span class="hljs-number">1</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">str</span> <span class="hljs-operator">=</span> (String)obj;<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.String (java.lang.Double and java.lang.String are in module java.base of loader &#x27;bootstrap&#x27;)</span><br><span class="hljs-comment">        at com.broky.exception.ClassCastEx.main(ClassCastEx.java:7)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">InputMismatchExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">scan</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br>        <span class="hljs-type">int</span> <span class="hljs-variable">num</span> <span class="hljs-operator">=</span> scan.nextInt();<br>        System.out.println(num);<br>        <span class="hljs-comment">/*asd</span><br><span class="hljs-comment">        Exception in thread &quot;main&quot; java.util.InputMismatchException</span><br><span class="hljs-comment">        at java.base/java.util.Scanner.throwFor(Scanner.java:939)</span><br><span class="hljs-comment">        at java.base/java.util.Scanner.next(Scanner.java:1594)</span><br><span class="hljs-comment">        at java.base/java.util.Scanner.nextInt(Scanner.java:2258)</span><br><span class="hljs-comment">        at java.base/java.util.Scanner.nextInt(Scanner.java:2212)</span><br><span class="hljs-comment">        at com.broky.exception.InputMismatchEx.main(InputMismatchEx.java:8)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">NullPointerExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">int</span>[] arr = <span class="hljs-literal">null</span>;<br>        System.out.println(arr[<span class="hljs-number">3</span>]);<br><br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.NullPointerException: Cannot load from int array because &quot;arr&quot; is null</span><br><span class="hljs-comment">        at com.broky.exception.NullPointerEx.main(NullPointerEx.java:6)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">NumberFormatExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">str</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;abc&quot;</span>;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">a</span> <span class="hljs-operator">=</span> Integer.parseInt(str);<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.NumberFormatException: For input string: &quot;abc&quot;</span><br><span class="hljs-comment">        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)</span><br><span class="hljs-comment">        at java.base/java.lang.Integer.parseInt(Integer.java:660)</span><br><span class="hljs-comment">        at java.base/java.lang.Integer.parseInt(Integer.java:778)</span><br><span class="hljs-comment">        at com.broky.exception.NumberMismatchEx.main(NumberMismatchEx.java:6)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">ArrayIndexOutOfBoundExceptionDemo</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">int</span>[] arr = <span class="hljs-keyword">new</span> <span class="hljs-title class_">int</span>[<span class="hljs-number">3</span>];<br>        System.out.println(arr[<span class="hljs-number">3</span>]);<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3</span><br><span class="hljs-comment">        at com.broky.exception.XIndexOutOfBoundEx.main(XIndexOutOfBoundEx.java:6)*/</span><br><br>        <span class="hljs-type">String</span> <span class="hljs-variable">str</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;abc&quot;</span>;<br>        System.out.println(str.charAt(<span class="hljs-number">3</span>));<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; java.lang.StringIndexOutOfBoundsException: String index out of range: 3</span><br><span class="hljs-comment">        at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)</span><br><span class="hljs-comment">        at java.base/java.lang.String.charAt(String.java:711)</span><br><span class="hljs-comment">        at com.broky.exception.XIndexOutOfBoundEx.main(XIndexOutOfBoundEx.java:11)*/</span><br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        ArrayIndexOutOfBoundExceptionDemo();<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h2 id="三、异常处理机制"><a href="#三、异常处理机制" class="headerlink" title="三、异常处理机制"></a>三、异常处理机制</h2><p>在编写代码处理异常时，对于检查性异常，有两种不同的处理方式：</p>
<ul>
<li>使用 <strong>「try…catch…finally…」</strong> 语句块处理</li>
<li>在方法中使用 <strong>「throws&#x2F;throw」</strong> 关键词将异常交给方法调用者去处理</li>
</ul>
<h3 id="try…catch…finally…-关键字"><a href="#try…catch…finally…-关键字" class="headerlink" title="try…catch…finally… 关键字"></a><strong>try…catch…finally… 关键字</strong></h3><ul>
<li>使用 try 和 catch 关键字可以捕获异常。</li>
<li>try&#x2F;catch 代码块放在异常可能发生的地方。</li>
</ul>
<p>try&#x2F;catch代码块中的代码称为保护代码，使用 try&#x2F;catch 的语法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">try</span> &#123;<br>    ...<br>&#125; <span class="hljs-keyword">catch</span> (IOException ioException) &#123;<br>    ...<br>&#125; <span class="hljs-keyword">catch</span> (Exception exception) &#123;<br>    ...<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    ...<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p><strong>「try 块：」</strong></p>
<ul>
<li>try块中放可能发生异常的代码。</li>
<li>如果执行完try且不发生异常，则接着去执行finally块中的代码和finally后面的代码（如果有的话）。</li>
<li>如果程序发生异常，则尝试去匹配对应的catch块。</li>
</ul>
<p><strong>「catch 块：」</strong></p>
<ul>
<li>每一个catch块用于捕获并处理一个特定的异常，或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。</li>
<li>catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的，则虚拟机将使用这个catch块来处理异常。</li>
<li>在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量，其它块不能访问。</li>
<li>如果当前try块中发生的异常在后续的所有catch中都没捕获到，则先去执行finally，然后到这个方法的外部调用者中去匹配异常处理器。</li>
<li>如果try中没有发生异常，则所有的catch块将被忽略。</li>
</ul>
<p><strong>「需要注意的地方」</strong></p>
<p>1、try块中的局部变量和catch块中的局部变量（包括异常变量），以及finally中的局部变量，他们之间不可共享使用。</p>
<p>2、每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的，只有第一个匹配的catch会得到执行。匹配时，不仅运行精确匹配，也支持父类匹配，因此，如果同一个try块下的多个catch异常类型有父子关系，应该将子类异常放在前面，父类异常放在后面，这样保证每个catch块都有存在的意义。</p>
<p>3、Java中，异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方去。也就是说：当一个方法的某条语句发生异常时，这条语句的后面的语句不会再执行，它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行，异常被处理完后，执行流会接着在“处理了这个异常的catch代码块”后面接着执行。</p>
<p><strong>「finally 块：」</strong></p>
<ul>
<li>finally块不是必须的，通常是可选的。</li>
<li>无论异常是否发生，异常是否匹配被处理，finally中的代码都会执行。</li>
<li>一个try至少要有一个catch块，否则， 至少要有1个finally块。但是finally不是用来处理异常的，finally不会捕获和处理异常，处理异常的只能是catch块。</li>
<li>finally主要做一些清理工作，如流的关闭，数据库连接的关闭等。</li>
<li>finally块不管异常是否发生，只要对应的try执行了，则它一定也执行。只有一种方法让finally块不执行：<strong>「System.exit()」</strong> 。</li>
</ul>
<p>比较良好的编程习惯是：在try块中打开资源，在finally块中清理并释放这些资源，以免造成内存泄露。</p>
<p><strong>「需要注意的地方:」</strong></p>
<p>1、在同一try…catch…finally…块中，如果try中抛出异常，且有匹配的catch块，则先执行catch块，再执行finally块。如果没有catch块匹配，则先执行finally，然后去到上层的调用者中寻找合适的catch块。</p>
<p>2、在同一try…catch…finally…块中 ，try发生异常，且匹配的catch块中处理异常时也抛出异常，那么后面的finally也会执行：首先执行finally块，然后去上层调用者中寻找合适的catch块。</p>
<h3 id="throws-x2F-throw-关键字"><a href="#throws-x2F-throw-关键字" class="headerlink" title="throws&#x2F;throw 关键字"></a><strong>throws&#x2F;throw 关键字</strong></h3><ul>
<li><strong>「throws 关键字」</strong></li>
</ul>
<p>如果一个方法内部的代码会抛出检查性异常（checked exception），而方法自己又没有对这些异常完全处理掉，则java的编译器会要求你必须在方法的签名上使用 <strong>「throws」</strong> 关键字声明这些可能抛出的异常，否则编译不通过。</p>
<p>throws 是另一种处理异常的方式，它不同于try…catch…finally…，throws 关键字仅仅是将方法中可能出现的异常向调用者抛出，而自己则不具体处理。</p>
<p>采取这种异常处理的原因可能是：方法本身不知道如何处理这样的异常，或者说让调用者处理更好，调用者需要为可能发生的异常负责。</p>
<ul>
<li><strong>「throw 关键字」</strong></li>
</ul>
<p>我们也可以通过 throw 语句手动显式的抛出一个异常，throw语句的后面必须是一个异常对象。语法如下：</p>
<blockquote>
<p>❝ throw exceptionObject<br>❞</p>
</blockquote>
<p>throw 语句必须写在方法中，执行throw 语句的地方就是一个异常抛出点，它和由JRE自动形成的异常抛出点没有任何差别。</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">save</span><span class="hljs-params">(User user)</span> &#123;<br>    <span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>)<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">IllegalArgumentException</span>(<span class="hljs-string">&quot;User对象为空&quot;</span>);<br>    <span class="hljs-comment">//......</span><br>&#125;<br></code></pre></div></td></tr></table></figure>

<h3 id="try-catch-finally-的执行顺序"><a href="#try-catch-finally-的执行顺序" class="headerlink" title="try-catch-finally 的执行顺序"></a><strong>try-catch-finally 的执行顺序</strong></h3><p>try-catch-finally 执行顺序的相关问题可以说是各种面试中的「常客」了，尤其是 finally 块中带有 return 语句的情况。我们直接看几道面试题：</p>
<p><strong>「面试题一：」</strong></p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> test();<br>        System.out.println(result);<br>    &#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-title function_">test</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br>        <span class="hljs-keyword">try</span> &#123;<br>            i++;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Exception</span>();<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            i--;<br>            System.out.println(<span class="hljs-string">&quot;catch block i = &quot;</span> + i);<br>        &#125; <span class="hljs-keyword">finally</span> &#123;<br>        	i = <span class="hljs-number">10</span>; <br>            System.out.println(<span class="hljs-string">&quot;finally block i = &quot;</span> + i);<br>        &#125;<br>        <span class="hljs-keyword">return</span> i;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight text"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs text">try block, i = 1<br>finally block i = 10<br>10<br></code></pre></div></td></tr></table></figure>

<p>比较简单，程序抛出一个异常，然后被本方法的 catch 块捕获并进行了处理。</p>
<p><strong>「面试题二：」</strong></p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>    <span class="hljs-type">int</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> test2();<br>    System.out.println(result);<br>&#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-title function_">test2</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-comment">//try 语句块中有 return 语句时的整体执行顺序</span><br>    <span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br>    <span class="hljs-keyword">try</span> &#123;<br>        i++;<br>        System.out.println(<span class="hljs-string">&quot;try block, i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>        i++;<br>        System.out.println(<span class="hljs-string">&quot;catch block i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        i = <span class="hljs-number">10</span>;<br>        System.out.println(<span class="hljs-string">&quot;finally block i = &quot;</span> + i);<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight text"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs text">try block, i = 2<br>finally block i = 10<br>2<br></code></pre></div></td></tr></table></figure>

<p>是不是有点疑惑？明明我 try 语句块中有 return 语句，可为什么最终还是执行了 finally 块中的代码？</p>
<p>我们反编译这个类，看看这个 test2 方法反编译后的结果的实现：</p>
<figure class="highlight ldif"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ldif"><span class="hljs-attribute">0</span>: iconst_1<br><span class="hljs-attribute">1</span>: istore_0<br><span class="hljs-attribute">2</span>: iinc          0, 1<br><span class="hljs-attribute">5</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">8</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">11</span>: dup<br><span class="hljs-attribute">12</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">15</span>: ldc           <span class="hljs-comment">#15                 // String try block, i =</span><br><span class="hljs-attribute">17</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">20</span>: iload_0<br><span class="hljs-attribute">21</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">24</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">27</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">30</span>: iload_0<br><span class="hljs-attribute">31</span>: istore_1<br><span class="hljs-attribute">32</span>: bipush        10<br><span class="hljs-attribute">34</span>: istore_0<br><span class="hljs-attribute">35</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">38</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">41</span>: dup<br><span class="hljs-attribute">42</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">45</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">47</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">50</span>: iload_0<br><span class="hljs-attribute">51</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">54</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">57</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">60</span>: iload_1<br><span class="hljs-attribute">61</span>: ireturn<br><span class="hljs-attribute">62</span>: astore_1<br><span class="hljs-attribute">63</span>: iinc          0, 1<br><span class="hljs-attribute">66</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">69</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">72</span>: dup<br><span class="hljs-attribute">73</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">76</span>: ldc           <span class="hljs-comment">#9                  // String catch block i =</span><br><span class="hljs-attribute">78</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">81</span>: iload_0<br><span class="hljs-attribute">82</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">85</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">88</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">91</span>: iload_0<br><span class="hljs-attribute">92</span>: istore_2<br><span class="hljs-attribute">93</span>: bipush        10<br><span class="hljs-attribute">95</span>: istore_0<br><span class="hljs-attribute">96</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">99</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">102</span>: dup<br><span class="hljs-attribute">103</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">106</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">108</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">111</span>: iload_0<br><span class="hljs-attribute">112</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">115</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">118</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">121</span>: iload_2<br><span class="hljs-attribute">122</span>: ireturn<br><span class="hljs-attribute">123</span>: astore_3<br><span class="hljs-attribute">124</span>: bipush        10<br><span class="hljs-attribute">126</span>: istore_0<br><span class="hljs-attribute">127</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">130</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">133</span>: dup<br><span class="hljs-attribute">134</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">137</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">139</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">142</span>: iload_0<br><span class="hljs-attribute">143</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">146</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">149</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">152</span>: aload_3<br><span class="hljs-attribute">153</span>: athrow<br></code></pre></div></td></tr></table></figure>

<p>从反编译的指令可以看出来，无论程序是否出现异常，finally 代码块中的内容始终会被执行的原因就是，<strong>「编译器会将 finally 块中的代码复制两份并分别添加在 try 和 catch 的后面」</strong>。</p>
<p>可能有人会所疑惑，原本我们的 i 就被存储在局部变量表 0 位置，而最后 finally 中的代码也的确将 slot 0 位置填充了数值 10，可为什么最后程序依然返回的数值 2 呢？</p>
<p>仔细看字节码，你会发现在 return 语句返回之前，虚拟机会将待返回的值压入操作数栈，等待返回，即使 finally 语句块对 i 进行了修改，但是待返回的值已经确实的存在于操作数栈中了，所以不会影响程序返回结果。</p>
<p>参考IDEA将字节码反编译的java代码</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-title function_">test2</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-type">byte</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br><br>    <span class="hljs-type">int</span> var2;<br>    <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-type">int</span> i;<br>        <span class="hljs-keyword">try</span> &#123;<br>            i = i + <span class="hljs-number">1</span>;<br>            System.out.println(<span class="hljs-string">&quot;try block, i = &quot;</span> + i);<br>            <span class="hljs-type">int</span> <span class="hljs-variable">var1</span> <span class="hljs-operator">=</span> i;<br>            <span class="hljs-keyword">return</span> var1;<br>        &#125; <span class="hljs-keyword">catch</span> (ExceptionTest var6) &#123;<br>            i = i + <span class="hljs-number">1</span>;<br>            System.out.println(<span class="hljs-string">&quot;catch block i = &quot;</span> + i);<br>            var2 = i;<br>        &#125;<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        i = <span class="hljs-number">10</span>;<br>        System.out.println(<span class="hljs-string">&quot;finally block i = &quot;</span> + i);<br>    &#125;<br><br>    <span class="hljs-keyword">return</span> var2;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p><strong>「面试题三：」</strong></p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-title function_">test3</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-comment">//finally 语句块中有 return 语句</span><br>    <span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br>    <span class="hljs-keyword">try</span> &#123;<br>        i++;<br>        System.out.println(<span class="hljs-string">&quot;try block, i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>        i++;<br>        System.out.println(<span class="hljs-string">&quot;catch block i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        i++;<br>        System.out.println(<span class="hljs-string">&quot;finally block i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight text"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs text">try block, i = 2<br>finally block i = 3<br>3<br></code></pre></div></td></tr></table></figure>

<p>javap反编译结果</p>
<figure class="highlight ldif"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ldif"><span class="hljs-attribute">0</span>: iconst_1<br><span class="hljs-attribute">1</span>: istore_0<br><span class="hljs-attribute">2</span>: iinc          0, 1<br><span class="hljs-attribute">5</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">8</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">11</span>: dup<br><span class="hljs-attribute">12</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">15</span>: ldc           <span class="hljs-comment">#15                 // String try block, i =</span><br><span class="hljs-attribute">17</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">20</span>: iload_0<br><span class="hljs-attribute">21</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">24</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">27</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">30</span>: iload_0<br><span class="hljs-attribute">31</span>: istore_1<br><span class="hljs-attribute">32</span>: iinc          0, 1<br><span class="hljs-attribute">35</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">38</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">41</span>: dup<br><span class="hljs-attribute">42</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">45</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">47</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">50</span>: iload_0<br><span class="hljs-attribute">51</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">54</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">57</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">60</span>: iload_0<br><span class="hljs-attribute">61</span>: ireturn<br><span class="hljs-attribute">62</span>: astore_1<br><span class="hljs-attribute">63</span>: iinc          0, 1<br><span class="hljs-attribute">66</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">69</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">72</span>: dup<br><span class="hljs-attribute">73</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">76</span>: ldc           <span class="hljs-comment">#9                  // String catch block i =</span><br><span class="hljs-attribute">78</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">81</span>: iload_0<br><span class="hljs-attribute">82</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">85</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">88</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">91</span>: iload_0<br><span class="hljs-attribute">92</span>: istore_2<br><span class="hljs-attribute">93</span>: iinc          0, 1<br><span class="hljs-attribute">96</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">99</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">102</span>: dup<br><span class="hljs-attribute">103</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">106</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">108</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">111</span>: iload_0<br><span class="hljs-attribute">112</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">115</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">118</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">121</span>: iload_0<br><span class="hljs-attribute">122</span>: ireturn<br><span class="hljs-attribute">123</span>: astore_3<br><span class="hljs-attribute">124</span>: iinc          0, 1<br><span class="hljs-attribute">127</span>: getstatic     <span class="hljs-comment">#3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="hljs-attribute">130</span>: new           <span class="hljs-comment">#7                  // class java/lang/StringBuilder</span><br><span class="hljs-attribute">133</span>: dup<br><span class="hljs-attribute">134</span>: invokespecial <span class="hljs-comment">#8                  // Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span><br><span class="hljs-attribute">137</span>: ldc           <span class="hljs-comment">#14                 // String finally block i =</span><br><span class="hljs-attribute">139</span>: invokevirtual <span class="hljs-comment">#10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">142</span>: iload_0<br><span class="hljs-attribute">143</span>: invokevirtual <span class="hljs-comment">#11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="hljs-attribute">146</span>: invokevirtual <span class="hljs-comment">#12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="hljs-attribute">149</span>: invokevirtual <span class="hljs-comment">#13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="hljs-attribute">152</span>: iload_0<br><span class="hljs-attribute">153</span>: ireturn<br></code></pre></div></td></tr></table></figure>

<p>可以从它的字节码指令去看整个过程，而不要单单死记它的执行过程。</p>
<p>IDEA反编译代码</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-title function_">test3</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br><br>    <span class="hljs-keyword">try</span> &#123;<br>        ++i;<br>        System.out.println(<span class="hljs-string">&quot;try block, i = &quot;</span> + i);<br>    &#125; <span class="hljs-keyword">catch</span> (Exception var6) &#123;<br>        ++i;<br>        System.out.println(<span class="hljs-string">&quot;catch block i = &quot;</span> + i);<br>    &#125; <span class="hljs-keyword">finally</span> &#123;<br>        ++i;<br>        System.out.println(<span class="hljs-string">&quot;finally block i = &quot;</span> + i);<br>        <span class="hljs-keyword">return</span> i;<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>发现程序最终会采用 finally 代码块中的 return 语句进行返回，而直接忽略 try 语句块中的 return 指令。</p>
<h3 id="自定义异常"><a href="#自定义异常" class="headerlink" title="自定义异常"></a><strong>自定义异常</strong></h3><p>Java 的异常机制中所定义的所有异常不可能预见所有可能出现的错误，某些特定的情境下，则需要我们自定义异常类型来向上报告某些错误信息。</p>
<p>而自定义异常类型也是相当简单的，你可以选择继承 Throwable，Exception 或它们的子类，甚至你不需要实现和重写父类的任何方法即可完成一个异常类型的定义。</p>
<p>例如：</p>
<figure class="highlight text"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs text">public class MyException extends RuntimeException&#123; &#125; <br><br>public class MyException extends Exception&#123; &#125;<br></code></pre></div></td></tr></table></figure>

<p>按照惯例，自定义的异常应该总是包含如下的构造函数：</p>
<ul>
<li>一个无参构造函数</li>
<li>一个带有String参数的构造函数，并传递给父类的构造函数。</li>
<li>一个带有String参数和Throwable参数，并都传递给父类构造函数</li>
<li>一个带有Throwable 参数的构造函数，并传递给父类的构造函数。</li>
</ul>
<p>下面是IOException类的完整源代码，我们可以参考：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">IOException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Exception</span> &#123;<br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">long</span> <span class="hljs-variable">serialVersionUID</span> <span class="hljs-operator">=</span> <span class="hljs-number">7818375828146090155L</span>;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">IOException</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">super</span>();<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">IOException</span><span class="hljs-params">(String message)</span> &#123;<br>        <span class="hljs-built_in">super</span>(message);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">IOException</span><span class="hljs-params">(String message, Throwable cause)</span> &#123;<br>        <span class="hljs-built_in">super</span>(message, cause);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">IOException</span><span class="hljs-params">(Throwable cause)</span> &#123;<br>        <span class="hljs-built_in">super</span>(cause);<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>自定义异常示例</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.broky.exception;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">RuntimeException</span>&#123;<br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">long</span> <span class="hljs-variable">serialVersionUID</span> <span class="hljs-operator">=</span> -<span class="hljs-number">1234719074324978L</span>;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">MyException</span><span class="hljs-params">()</span>&#123;<br><br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">MyException</span><span class="hljs-params">(String message)</span>&#123;<br>        <span class="hljs-built_in">super</span>(message);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyException</span>(<span class="hljs-string">&quot;自定义运行时异常&quot;</span>);<br>        <span class="hljs-comment">/*Exception in thread &quot;main&quot; com.broky.exception.MyException: 自定义运行时异常</span><br><span class="hljs-comment">        at com.broky.exception.MyException.main(MyException.java:15)*/</span><br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>



<h3 id="异常的注意事项"><a href="#异常的注意事项" class="headerlink" title="异常的注意事项"></a><strong>异常的注意事项</strong></h3><p>1、当子类重写父类的带有 throws声明的函数时，其throws声明的异常必须在父类异常的可控范围内——用于处理父类的throws方法的异常处理器，必须也适用于子类的这个带throws方法 。这是为了支持多态。</p>
<p>例如，父类方法throws 的是2个异常，子类就不能throws 3个及以上的异常。父类throws IOException，子类就必须throws IOException或者IOException的子类。</p>
<p>2、Java程序可以是多线程的。每一个线程都是一个独立的执行流，独立的函数调用栈。如果程序只有一个线程，那么没有被任何代码处理的异常 会导致程序终止。如果是多线程的，那么没有被任何代码处理的异常仅仅会导致异常所在的线程结束。</p>
<p>也就是说，Java中的异常是线程独立的，线程的问题应该由线程自己来解决，而不要委托到外部，也不会直接影响到其它线程的执行。</p>
<h2 id="四、异常使用时的常见错误"><a href="#四、异常使用时的常见错误" class="headerlink" title="四、异常使用时的常见错误"></a>四、异常使用时的常见错误</h2><h3 id="1、将异常直接显示在页面或客户端"><a href="#1、将异常直接显示在页面或客户端" class="headerlink" title="1、将异常直接显示在页面或客户端"></a><strong>1、将异常直接显示在页面或客户端</strong></h3><p>将异常直接打印在客户端的例子屡见不鲜，一旦程序运行出现异常，默认情况下容器将异常堆栈信息直接打印在页面上。从客户角度来说，任何异常都没有实际意义，绝大多数的客户也根本看不懂异常信息，软件开发也要尽量避免将异常直接呈现给用户，一定要在前端展示层对异常进行封装后展示。目前绝大多数应用都是前后端分离的模式，这种直接打印异常的情况已经相对改善了很多，不过我们在编码时还是要特别注意下这个原则。</p>
<h3 id="2、忽略异常"><a href="#2、忽略异常" class="headerlink" title="2、忽略异常"></a><strong>2、忽略异常</strong></h3><p>如下异常处理只是将异常输出到控制台，没有任何意义。而且这里出现了异常并没有中断程序，进而调用代码继续执行，导致更多的异常。</p>
<figure class="highlight text"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs text">public void retrieveObjectById(Long id) &#123;<br>    try &#123;<br>        //..some code that throws SQLException<br>    &#125; catch (SQLException ex) &#123;<br>        /**<br>          *了解的人都知道，这里的异常打印毫无意义，仅仅是将错误堆栈输出到控制台。<br>          * 而在 Production 环境中，需要将错误堆栈输出到日志。<br>          * 而且这里 catch 处理之后程序继续执行，会导致进一步的问题*/<br><br>        ex.printStacktrace();<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>捕获了异常缺不进行处理，这是我们在写代码时候的大忌，可以重构成：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">retrieveObjectById</span><span class="hljs-params">(Long id)</span> &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-comment">//..some code that throws SQLException</span><br>    &#125; <span class="hljs-keyword">catch</span> (SQLException ex) &#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;Exception in retieveObjectById”, ex);</span><br><span class="hljs-string">    &#125; finally &#123;</span><br><span class="hljs-string">        //clean up resultset, statement, connection etc</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string">&#125;</span><br></code></pre></div></td></tr></table></figure>

<h3 id="3、将异常包含在循环语句块中"><a href="#3、将异常包含在循环语句块中" class="headerlink" title="3、将异常包含在循环语句块中"></a><strong>3、将异常包含在循环语句块中</strong></h3><p>如下代码所示，异常包含在 for 循环语句块中。</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100</span>; i++) &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>    &#125; <span class="hljs-keyword">catch</span> (XXXException e) &#123;<br>        <span class="hljs-comment">//....</span><br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>我们都知道异常处理占用系统资源。一看，大家都认为不会犯这样的错误。换个角度，类 A 中执行了一段循环，循环中调用了 B 类的方法，B 类中被调用的方法却又包含 try-catch 这样的语句块。褪去类的层次结构，代码和上面如出一辙。</p>
<h3 id="4、利用-Exception-捕捉所有潜在的异常"><a href="#4、利用-Exception-捕捉所有潜在的异常" class="headerlink" title="4、利用 Exception 捕捉所有潜在的异常"></a><strong>4、利用 Exception 捕捉所有潜在的异常</strong></h3><p>一段方法执行过程中抛出了几个不同类型的异常，为了代码简洁，利用基类 Exception 捕捉所有潜在的异常，如下例所示：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">retrieveObjectById</span><span class="hljs-params">(Long id)</span> &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-comment">//...抛出 IOException 的代码调用</span><br>        <span class="hljs-comment">//...抛出 SQLException 的代码调用</span><br>    &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>        <span class="hljs-comment">//这里利用基类 Exception 捕捉的所有潜在的异常，如果多个层次这样捕捉，会丢失原始异常的有效信息</span><br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;Exception in retieveObjectById”, e);</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string">&#125;</span><br></code></pre></div></td></tr></table></figure>

<p>大部分程序员都会有这种写法，为了省事简便，直接一个顶层的exception来捕获所有可能出现的异常，这样虽然可以保证异常肯定会被捕捉到，但是程序却无法针对不同的错误异常进行对应正确的处理，可以重构成：</p>
<figure class="highlight java"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">retrieveObjectById</span><span class="hljs-params">(Long id)</span> &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-comment">//..some code that throws RuntimeException, IOException, SQLException</span><br>    &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>        <span class="hljs-comment">//仅仅捕捉 IOException</span><br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-comment">/*指定这里 IOException 对应的错误代码*/</span>code, <span class="hljs-string">&quot;Exception in retieveObjectById”, e);</span><br><span class="hljs-string">    &#125; catch (SQLException e) &#123;</span><br><span class="hljs-string">        //仅仅捕捉 SQLException</span><br><span class="hljs-string">        throw new RuntimeException(/*指定这里 SQLException 对应的错误代码*/code, &quot;</span>Exception in retieveObjectById”, e);<br>    &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>



<h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><section class="footnotes"><div class="footnote-list"><ol><li><span id="fn:1" class="footnote-text"><span><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/353871211">https://zhuanlan.zhihu.com/p/353871211</a>
<a href="#fnref:1" rev="footnote" class="footnote-backref"> ↩</a></span></span></li><li><span id="fn:2" class="footnote-text"><span><a target="_blank" rel="noopener" href="https://www.cnblogs.com/13roky/p/14672500.html">https://www.cnblogs.com/13roky/p/14672500.html</a>
<a href="#fnref:2" rev="footnote" class="footnote-backref"> ↩</a></span></span></li></ol></div></section>
            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Java/">Java</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Java%E5%9F%BA%E7%A1%80/">Java基础</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/03/03/StringBuffer%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%AE%9E%E7%8E%B0/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">StringBuffer线程安全的实现</span>
                        <span class="visible-mobile">Previous</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/02/26/JVM%E7%AC%94%E8%AE%B0/">
                        <span class="hidden-mobile">JVM</span>
                        <span class="visible-mobile">Next</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;TOC</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">Search</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">keyword</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
        typing(title);
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
